package com.goldcn.ftp.service;

import com.goldcn.common.util.UuidUtils;
import com.goldcn.config.FTPConfigure;
import com.goldcn.enumeration.ErrorCodeEnum;
import com.goldcn.file.util.CommonTools;
import com.goldcn.file.vo.FileVo;
import org.apache.commons.io.IOUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

/**
 * @Author mail:
 * Date: 2017/10/16
 * Time: 10:46
 * To change this template use File | Settings | File Templates.
 */
@Service
@Transactional
public class FtpService {

    private Logger logger = Logger.getLogger(FtpService.class);

    @Autowired
    FTPConfigure ftpConfigure;

    private static final String temp_path = System.getProperty("user.dir") + File.separator + "image" + File.separator;

    private static FTPClient ftpClient;


    /**
     * ftp上传单个文件
     *
     * @throws IOException
     */
    public Object uploadFiles1() throws IOException {

        FileInputStream fis = null;
        FileVo vo = new FileVo();
        try {
            connectFtp();
            String suffix = "txt";
            String fileName = "test.txt";
            String filePath = temp_path + fileName;


            File srcFile = new File(filePath);

            fis = new FileInputStream(srcFile);

            ftpClient.setControlEncoding("gbk");

            boolean success = ftpClient.storeFile(fileName, fis);
            if (success) {
                vo.setFileName(fileName);
                // vo.setFileSize(file.getSize());
                vo.setFileSuffix(suffix);
                // vo.setFileUploadName(file.getOriginalFilename());
                deteleTempFile(temp_path);
            } else {
                vo.setErrorCode("001");
                vo.setErrorDesc("上传失败");
            }
            return vo;
        } catch (NumberFormatException e) {
            System.out.println("FTP端口配置错误:不是数字:");
            throw e;
        } catch (FileNotFoundException e) {
            throw new FileNotFoundException();
        } catch (IOException e) {
            throw new IOException(e);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fis);
            try {
                ftpClient.disconnect();
            } catch (IOException e) {
                throw new RuntimeException("关闭FTP连接发生异常！", e);
            }
        }
        return vo;
    }


    /**
     * ftp上传单个文件
     *
     * @throws IOException
     */
    public Object uploadFiles(MultipartFile file) throws IOException {

        FileInputStream fis = null;
        FileVo vo = new FileVo();
        try {
            connectFtp();
            String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
            String fileName = UuidUtils.uuid() + suffix;
            String filePath = temp_path + fileName;

            this.saveLoaclFolder(file, filePath);
            File srcFile = new File(filePath);

            fis = new FileInputStream(srcFile);

            ftpClient.setControlEncoding("gbk");

            boolean success = ftpClient.storeFile(fileName, fis);
            if (success) {
                vo.setFileName(fileName);
                vo.setFileSize(file.getSize());
                vo.setFileSuffix(suffix);
                vo.setFileUploadName(file.getOriginalFilename());
                deteleTempFile(temp_path);
            } else {
                vo.setErrorCode("001");
                vo.setErrorDesc("上传失败");
            }
            return vo;
        } catch (NumberFormatException e) {
            System.out.println("FTP端口配置错误:不是数字:");
            throw e;
        } catch (FileNotFoundException e) {
            throw new FileNotFoundException();
        } catch (IOException e) {
            throw new IOException(e);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fis);
            try {
                ftpClient.disconnect();
            } catch (IOException e) {
                throw new RuntimeException("关闭FTP连接发生异常！", e);
            }
        }
        return vo;
    }


    /**
     * FTP单个文件下载
     *
     * @param destFileName 要下载的文件名
     */
    public void downLoad(String destFileName, HttpServletRequest request, HttpServletResponse resp) throws IOException {
        BufferedInputStream bis = null;
        OutputStream os = null;
        try {
            connectFtp();
            System.out.println("destFileName:" + destFileName + ",downloadName:" + destFileName);
            StringBuffer file = new StringBuffer();
            file.append(temp_path).append(destFileName);
            //从ftp下载至本地服务器
            boolean b = ftpClient.retrieveFile(destFileName, new FileOutputStream(file.toString()));


            //下载到用户端
            resp.setHeader("conent-type", "application/octet-stream");
            resp.setContentType("application/octet-stream");
            resp.setHeader("Content-Disposition", "attachment; filename=" + new String(destFileName.getBytes("ISO-8859-1"), "UTF-8"));

            os = resp.getOutputStream();

            BufferedOutputStream bos = new BufferedOutputStream(os);

            InputStream is = new FileInputStream(file.toString());

            int length = 0;
            byte[] temp = new byte[10 * 1024];
            bis = new BufferedInputStream(is);
            while ((length = bis.read(temp)) != -1) {
                bos.write(temp, 0, length);
            }
            bos.flush();
            bis.close();
            bos.close();
            is.close();
            deteleTempFile(temp_path);
        } catch (FileNotFoundException e) {
            throw new FileNotFoundException();
        } catch (IOException e) {
            throw new IOException(e);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                ftpClient.disconnect();
            } catch (IOException e) {
                throw new RuntimeException("关闭FTP连接发生异常！", e);
            }
        }
    }

    public boolean deleteFtpFile(String fileName) throws IOException {
        boolean success = false;
        ftpClient = new FTPClient();
        try {
            connectFtp();
            success = ftpClient.deleteFile(fileName);
            ftpClient.logout();
        } catch (IOException e) {
            success = false;
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    logger.error(e.getMessage());
                }
            }
            return success;
        }
    }

    public boolean connectFtp() throws Exception {

        ftpClient = new FTPClient();

        try {
            ftpClient.connect(ftpConfigure.getIp(), ftpConfigure.getPort());
            ftpClient.setBufferSize(1024);
            ftpClient.setControlEncoding("GBK");


            logger.info("Connected to " + ftpConfigure.getIp() + ".");
            logger.info("FTP server reply code:" + ftpClient.getReplyCode());

            //登录
            if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
                if (ftpClient.login(ftpConfigure.getUserName(), ftpConfigure.getPassword())) {

                    // Path is the sub-path of the FTP path
                    logger.info("登录成功...");
                    //设置上传目录
                    ftpClient.changeWorkingDirectory(ftpConfigure.getDirectory());
                    ftpClient.enterLocalPassiveMode();

                    //设置被动模式
                    ftpClient.enterLocalPassiveMode();
                    //设置文件类型（二进制）
                    ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);

                    return true;
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
            throw new Exception("ftp连接失败", e);
        }
        return true;
    }


    public boolean connectFtp1() throws Exception {
        ftpClient = new FTPClient();
        boolean flag = false;
        int reply;
        try {
            if (ftpConfigure.getPort() == null) {
                ftpClient.connect(ftpConfigure.getIp(), 33221);
            } else {
                ftpClient.connect(ftpConfigure.getIp(), ftpConfigure.getPort());
            }
            //ftp登陆
            boolean b = ftpClient.login(ftpConfigure.getUserName(), ftpConfigure.getPassword());

            ftpClient.enterLocalPassiveMode();
            ftpClient.setBufferSize(ftpConfigure.getPermitSize());

            ftpClient.enterLocalPassiveMode();

            //设置上传路径
            ftpClient.changeWorkingDirectory(ftpConfigure.getDirectory());
            //设置文件传输类型
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            /*//检查延时
            reply = ftpClient.getReplyCode();
            //如果延时不在200到300之间，就关闭连接
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                return flag;
            }*/
            return true;
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
    }


    /**
     * 关闭ftp连接
     */
    public static void closeFtp() {
        if (ftpClient != null && ftpClient.isConnected()) {
            try {
                ftpClient.logout();
                ftpClient.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 将原图保存在临时文件夹
     *
     * @param filePath 原图文件路径
     * @param file     原图文件流
     * @return
     */
    private void saveLoaclFolder(MultipartFile file, String filePath) {
        FileOutputStream fos = null;
        try {
            this.creatLocalFolder();
            fos = new FileOutputStream(filePath);
            fos.write(file.getBytes());
        } catch (Exception e) {
            logger.info(e.getMessage());
            throw CommonTools.createException(ErrorCodeEnum.saveLocalFolderFailure);
        } finally {
            try {
                if (fos != null)
                    fos.close();
            } catch (Exception e) {

            }
        }
    }

    /**
     * 获取本地存储图片文件夹 没有则创建
     */
    private void creatLocalFolder() {
        File f = new File(temp_path);
        if (!f.exists()) {
            f.mkdirs();
        }
    }

    /**
     * 删除临时文件夹下的文件
     *
     * @param temp_path
     */
    private void deteleTempFile(String temp_path) {
        File folder = new File(temp_path);
        if (!(folder.isFile() || folder.listFiles().length == 0)) {
            File[] files = folder.listFiles();
            for (int i = 0; i < files.length; i++) {
                deteleTempFile(files[i].getPath());
                files[i].delete();
            }
        }
    }
}
